import { WsServer, WsConnection } from 'tsrpc';
import { ServiceType } from '../shared/protocols/serviceProto';
import { Logger } from './utils/Logger';
import { DatabaseManager } from './database/DatabaseManager';
import { RoomManager } from '../game/RoomManager';
import { PlayerManager } from '../game/PlayerManager';
import { Config } from './config/Config';

export class GameServer {
    private static _instance: GameServer;
    private server: WsServer<ServiceType>;
    private logger: Logger;
    private db: DatabaseManager;
    private roomManager: RoomManager;
    private playerManager: PlayerManager;

    private constructor() {
        this.logger = new Logger();
        this.server = new WsServer<ServiceType>();
        this.db = new DatabaseManager();
        this.roomManager = new RoomManager();
        this.playerManager = new PlayerManager();
    }

    public static get instance(): GameServer {
        if (!GameServer._instance) {
            GameServer._instance = new GameServer();
        }
        return GameServer._instance;
    }

    public async initialize(): Promise<void> {
        try {
            // 初始化配置
            await Config.initialize();

            // 初始化数据库连接
            await this.db.initialize();

            // 初始化服务器
            await this.initializeServer();

            // 初始化管理器
            await this.roomManager.initialize();
            await this.playerManager.initialize();

            this.logger.info('Game server initialized successfully');
        } catch (error) {
            this.logger.error('Failed to initialize game server', error);
            throw error;
        }
    }

    private async initializeServer(): Promise<void> {
        // 实现API
        this.implementApis();

        // 注册消息处理器
        this.registerMessageHandlers();

        // 注册连接事件
        this.server.flows.postConnectFlow.push(async (conn: WsConnection<ServiceType>) => {
            this.logger.info(`Client connected: ${conn.id}`);
            return { isSuccess: true };
        });

        // 注册断开连接事件
        this.server.flows.postDisconnectFlow.push(async (conn: WsConnection<ServiceType>) => {
            this.logger.info(`Client disconnected: ${conn.id}`);
            await this.playerManager.handleDisconnect(conn.id);
        });

        // 启动服务器
        await this.server.start();
        this.logger.info(`Server started on port ${Config.get('SERVER_PORT')}`);
    }

    private implementApis(): void {
        // 实现登录API
        this.server.implementApi('user/Login', async (call: { req: { username: string }, conn: WsConnection<ServiceType> }) => {
            try {
                const result = await this.playerManager.handleLogin(call.req);
                return { isSuccess: true, res: result };
            } catch (error: unknown) {
                const err = error as Error;
                this.logger.error('Login failed', err);
                return { isSuccess: false, err: { code: 'LOGIN_FAILED', message: err.message } };
            }
        });

        // 实现加入房间API
        this.server.implementApi('game/JoinRoom', async (call: { req: { roomId: string }, conn: WsConnection<ServiceType> }) => {
            try {
                const result = await this.roomManager.handleJoinRoom(call.req, call.conn.id);
                return { isSuccess: true, res: result };
            } catch (error: unknown) {
                const err = error as Error;
                this.logger.error('Join room failed', err);
                return { isSuccess: false, err: { code: 'JOIN_ROOM_FAILED', message: err.message } };
            }
        });
    }

    private registerMessageHandlers(): void {
        // 注册玩家移动消息处理
        this.server.listenMsg('game/PlayerMove', async (call: { msg: { direction: string }, conn: WsConnection<ServiceType> }) => {
            try {
                await this.roomManager.handlePlayerMove(call.msg, call.conn.id);
            } catch (error) {
                this.logger.error('Handle player move failed', error);
            }
        });
    }

    public broadcastToRoom(roomId: string, msgName: string, msg: any): void {
        const room = this.roomManager.getRoom(roomId);
        if (room) {
            room.players.forEach((player) => {
                const conn = this.server.getConnection(player.connectionId);
                if (conn) {
                    conn.sendMsg(msgName, msg);
                }
            });
        }
    }

    public getServer(): WsServer<ServiceType> {
        return this.server;
    }
} 